/*
 * Moon Kids' Paradise
 * (c)1995,1996 Bio_100%
 */
#define ASL_USE_MACRO

#include	<system.h>
#include	<v93.h>
#include	<nt.h>
#include	<soundbox.h>
#include	<adp.h>
#include	<farl.h>
#include	<asl.h>
#include	<agl.h>
#include	<common.h>
#include	<libm.h>
#include	<intlib.h>
#include	<pio.h>

#define Sin8(angle)                SinTable8[(angle) & 0xff]
#define Cos8(angle)                SinTable8[((angle) & 0xff)+64]

// ファイルヘッダーチェック用
#define ID_RIFF 'FFIR'
#define ID_WAVE 'EVAW'
#define ID_FMT  ' tmf'

#define	DAR_WHITE	160+137
#define	DAR_NEC		160+144+12
#define	DAR_BIO		160+144+12+1

#define	MAXCHAR		512
#define	MAXSCT		2048
#define	MAXMSL		3
#define	MAXPCM		3
#define	FADERATE	64
#define	MAXSPEED	3
#define	MAPX		16
#define	MAXENEMY	8
#define	MAXBAKU		32
#define	MAXSTAR		16

int SinTable8[256+64] = {
	    0,   6,  13,  19,  25,  31,  38,  44,
	   50,  56,  62,  68,  74,  80,  86,  92,
	   98, 104, 109, 115, 121, 126, 132, 137,
	  142, 147, 152, 157, 162, 167, 172, 177,
	  181, 185, 190, 194, 198, 202, 206, 209,
	  213, 216, 220, 223, 226, 229, 231, 234,
	  237, 239, 241, 243, 245, 247, 248, 250,
	  251, 252, 253, 254, 255, 255, 256, 256,

/* _CosTable8 */
	  256, 256, 256, 255, 255, 254, 253, 252,
	  251, 250, 248, 247, 245, 243, 241, 239,
	  237, 234, 231, 229, 226, 223, 220, 216,
	  213, 209, 206, 202, 198, 194, 190, 185,
	  181, 177, 172, 167, 162, 157, 152, 147,
	  142, 137, 132, 126, 121, 115, 109, 104,
	   98,  92,  86,  80,  74,  68,  62,  56,
	   50,  44,  38,  31,  25,  19,  13,   6,

	    0,  -6, -13, -19, -25, -31, -38, -44,
	  -50, -56, -62, -68, -74, -80, -86, -92,
	  -98,-104,-109,-115,-121,-126,-132,-137,
	 -142,-147,-152,-157,-162,-167,-172,-177,
	 -181,-185,-190,-194,-198,-202,-206,-209,
	 -213,-216,-220,-223,-226,-229,-231,-234,
	 -237,-239,-241,-243,-245,-247,-248,-250,
	 -251,-252,-253,-254,-255,-255,-256,-256,

	 -256,-256,-256,-255,-255,-254,-253,-252,
	 -251,-250,-248,-247,-245,-243,-241,-239,
	 -237,-234,-231,-229,-226,-223,-220,-216,
	 -213,-209,-206,-202,-198,-194,-190,-185,
	 -181,-177,-172,-167,-162,-157,-152,-147,
	 -142,-137,-132,-126,-121,-115,-109,-104,
	  -98, -92, -86, -80, -74, -68, -62, -56,
	  -50, -44, -38, -31, -25, -19, -13,  -6,

	    0,   6,  13,  19,  25,  31,  38,  44,
	   50,  56,  62,  68,  74,  80,  86,  92,
	   98, 104, 109, 115, 121, 126, 132, 137,
	  142, 147, 152, 157, 162, 167, 172, 177,
	  181, 185, 190, 194, 198, 202, 206, 209,
	  213, 216, 220, 223, 226, 229, 231, 234,
	  237, 239, 241, 243, 245, 247, 248, 250,
	  251, 252, 253, 254, 255, 255, 256, 256
	};

unsigned long pcmblock = 0L;
unsigned char pcmbuffer[65000];

// ADPファイルヘッダー用構造体
typedef struct adpfileheader_t{
	unsigned long   afFileID;             // RIFF
	unsigned long   afFileSize;
	unsigned long   afFileType;           // WAVE
	unsigned long   afFormatID;           // fmt
	unsigned long   afFormatSize;
	unsigned short  afFormatType;         // フォーマットタイプ
	unsigned short  afNumberOfChannel;    // チャンネル数
	unsigned long   afSamplingRate;       // サンプリングレート
	unsigned long   afTransferByte;       // 転送レート
	unsigned short  afSampleCount;        // サンプル数
	unsigned short  afBitOfNumber;        // 量子化ビット
	unsigned long   afDataID;             // データＩＤ
	unsigned long   afDataSize;           // データサイズ
	}ADPFILEHEAD;
ADPFILEHEAD     aFileHead[MAXPCM];
struct PCMINFO  pInfo[MAXPCM];
struct PCMVOL	pcmvol;

int fh;
int	charnumber = 0;
static unsigned int randomseed = 100;	// seed
unsigned short	workdat[512];

ASLSct		sct;
ASLSource	src[MAXCHAR];
unsigned short  buf[163840];
unsigned char	map[MAPX];

int	StrX;			// 文字表示位置
int	StrY;			// 文字表示位置
int	pauseflag = 0;
int	aflag = 0;
int	skipflag = 0;
int	stage = 0;
int	deadcount = 0;
int	timecount;
int	gflag = 0;
int	strnum = 0;
int	seedcount = 0;
unsigned char *strdat[6]={
	"｢ｽﾋﾟｰﾄﾞ ｵｰﾊﾞｰ｣",
	"  ｢ｻﾖｳﾅﾗ･･･｣ ",
	" ｢ｼﾅﾊﾞ ﾓﾛﾄﾓ｣ ",
	"  ｢ﾊﾘﾉ ﾔﾏ｣   ",
	"｢ﾉｰﾃﾝ ﾁｮｸｹﾞｷ｣",
	" ｢ｼﾞｶﾝｷﾞﾚ｣"};


/* 自機 */
struct	status{
	int	x;
	int	y;
	int	pat;
	int	speed;
	int	xspeed;
	int	yspeed;
	int	flag;
	int	mcount;
	int	deg;
	}ship;

struct status enemy[MAXENEMY];
struct status baku[MAXBAKU];
struct status star[MAXSTAR];

extern unsigned short i5c4yuv_col[];

int main (void);
void title (void);
void gamemain (void);
void datcopy (void);
void hedload (int bank, unsigned char *filename);
void aicload (unsigned short bank, unsigned char *filename);
void writetex (int bank, int x, int y, int data);
void srcset (unsigned short bank, int xsize, int ysize, int xnum, int ynum);
void InitSystem (void);
void InitScreen (void);
void StrDsp (int x, int y, int z, unsigned char *str);
void sprput (int x, int y, int r, int z, int pat);
void dspwait (void);
void waitbutton (void);
void shipcontrol (void);
void shipinit (void);
int random (int num);
void mapinit (void);
void mapdsp (void);
void shipdsp (void);
int adpload (int num, unsigned char *filename);
int hitcheck (int num);
void numdsp (int x, int y, unsigned long val);
void PaletteChange (int palettenumber, unsigned short yuv);
void PaletteChangeBW (int mode, int start, int end);
void PaletteFadeBlack (int mode, int start, int end);
void PaletteFadeWhite (int mode, int start, int end);
int buttoncheck (void);
void Wait (int c);
void logodsp (void);
void MakePaletteDataBlack (int i, int j);
void MakePaletteDataWhite (int i, int j);
void gameover(void);
void bakuinit(void);
void bakucontrol(void);
void bakudsp(void);
void stageclear(void);
void enemyinit(void);
void enemycontrol(void);
void enemydsp(void);
void starinit(void);
void starcontrol(void);
void stardsp(void);
void ending(void);

/*
 * メイン
 */
int
main()
	{
	int	i,j;
	int	xx,yy;

	// 初期化
	cache_enable();                               // キャッシュ開始
	DevInit();                                    // 各種デバイス初期化
	InitSystem();
	InitScreen();
	FX73init();
	FX73_cmap_i5c4();
	FarlInit();
	// もう一度初期化しないとADPCMか色がおかしくなる
	DevInit();
	InitSystem();

	AdpcmVolume(CHANNEL_1, MIN_PCM_VOLUME, MIN_PCM_VOLUME);
	AdpcmVolume(CHANNEL_2, MIN_PCM_VOLUME, MIN_PCM_VOLUME);
	AdpcmInit();
	AdpcmVolume(CHANNEL_1, MAX_PCM_VOLUME, MAX_PCM_VOLUME);
	AdpcmVolume(CHANNEL_2, MAX_PCM_VOLUME, MAX_PCM_VOLUME);

	pcmvol.pvoll = 0x28;
	pcmvol.pvolr = 0x28;
	set_pcm_vol(&pcmvol);

	KINGScreen(0);								// 画面モード16m色
	KINGDispOff();								// HuC6272 表示オフ
	KINGCylinder(KING_BG0,1);					// 茶筒モード
	KINGChangeSize0(DISP_NORMAL);				// 画面幅設定
	dispoff(bg | spr | rain | bg1 | bg2 | bg3);	// 他画面オフ
	dispon(bg | spr | bg0 );							// 画面ON
	KINGCls(KING_BG0);							// 画面消去
	KINGDispOff();								// HuC6272 表示オン

	VSyncInt();

	charnumber = 0;
	hedload(0,"MOONKP00.HED");

	// スプライトが表示される領域の設定
	ASLSetSpriteWindow( 0, 0, 255, 239 );

	StrDsp(16,200,256,"Now Loading...\nSprite 2/5");
	dspwait();
	hedload(1,"MOONKP01.HED");
	StrDsp(16,200,256,"Now Loading...\nSprite 3/5");
	dspwait();
	hedload(2,"MOONKP02.HED");
	StrDsp(16,200,256,"Now Loading...\nSprite 4/5");
	dspwait();
	hedload(3,"LOGO.HED");
	StrDsp(16,200,256,"Now Loading...\nSprite 5/5");
	dspwait();
	hedload(4,"SEXY.HED");

	get_pad();
	skipflag = 0;
	FX73_cmap_i5c4();
	logodsp();

	title();

	return	0;
	}

/*
 * タイトル
 */
void
title()
	{
	int	i,a;

	skipflag = 0;
	FX73_cmap_i5c4();
	a = 0;
	randomseed = 0;
	while(1)
		{
		randomseed++;
		a++;
		if ( a > 50 ) a = 0;
		get_pad();
		if ( pad00.KD_TRG & KP_run || pad00.KD_TRG & KP_1 ) break;
		StrDsp(36,64,512,"Moon Kids'");
		StrDsp(100,96,512,"Paradise");
		if ( a < 30 )
			{
			StrDsp(52,170,256,"Push Run Button");
			}
//		StrDsp(20,204,256,"(C)NECﾎｰﾑｴﾚｸﾄﾛﾆｸｽ");
		StrDsp(20,220,256,"(C)Bio100%");
		dspwait();
		}
	stage = 0;
	for ( i = 0 ; i < MAXENEMY ; i++ )
		{
		enemy[i].flag = 0;
		}
	gamemain();
	}

/*
 * ゲームメイン
 */
void
gamemain()
	{
	int	i,a;
	unsigned char *dat[8]={
		"Stage 1","Stage 2","Stage 3","Stage 4","Stage 5","Stage 6","Stage 7",
		"Final Stage"};

	for ( i = 0 ; i < MAXBAKU ; i++ )
		{
		baku[i].flag = 0;
		}
	FX73_cmap_i5c4();
	mapinit();
	starinit();
	shipinit();
	aflag = 0;
	deadcount = 0;
	a = stage + 1;
	for ( i = 0 ; i < 60 ; i++ )
		{
		aflag++;
		if ( aflag > 15 ) aflag = 0;
		sprput(32,100,0,256,ship.pat+aflag/8);
		StrDsp(50,100,256,dat[stage]);
		dspwait();
		}

	// メインループ
	while(1)
		{
		aflag++;
		if ( aflag > 15 ) aflag = 0;
		gflag++;
		if ( gflag > 24 ) gflag = 0;
		timecount--;
		if ( timecount < 0 )
			{
			timecount = 0;
			ship.flag = 0;
			bakuinit();
			strnum = 5;
			}
		if ( pauseflag )
			{
			// 一時停止
			while(1)
				{
				get_pad();
				if ( pad00.KD_TRG & KP_run )
					{
					pauseflag = 0;
					break;
					}
				}
			}
		shipcontrol();
		bakucontrol();
		enemycontrol();
		datcopy();
		dspwait();
		}
	}

/*
 * 画面表示
 */
void
datcopy()
	{
	stardsp();
	mapdsp();
	enemydsp();
	shipdsp();
	bakudsp();
	// ミサイル
	// 文字情報
	numdsp(160,16,timecount);
	}

/*
 * HEDファイルの読み込み
 */
void
hedload(int bank,unsigned char *filename)
	{
	int	fp, c,i,j;
	int	p,q,r,s;

	pio_putstr( "HED Data Loading..." );
	// 読み込み
	fp = pio_fopen(filename, "rb" );
	if ( fp == -1 )
		{
		pio_putstr( "\nCannot Open HED File.\n" );
		return;
		}
//	c = (256*256+4) * 2;
	c = 8;
	pio_fread(fp,c,(char *)buf);
	c = 0;
	p = buf[c];
	c++;
	q = buf[c];
	c++;
	r = buf[c];
	c++;
	s = buf[c];

	c = (p*r*q*s) * 2;
	pio_fread(fp,c,(char *)buf);
	c = 0;
	for ( i = 0 ; i < q*s ; i++ )
		{
		for ( j = 0 ; j < p*r ; j++ )
			{
			writetex(bank,j,i,buf[c]);
			c++;
			}
		}
	srcset(bank,p,q,r,s);
	pio_putstr( "done.\n" );
	pio_fclose(fp);
	return;
	}

/*
 * AICファイルの読み込み
 */
void
aicload(unsigned short bank, unsigned char *filename)
	{
	int	fp, i, num;
	int	x,y;

	// 初期化
//	FX73init();
//	FarlInit();
	pio_putstr( "Sprite data loading..." );

	// 読み込み
	fp = pio_fopen(filename, "rb" );
	if ( fp == -1 )
		{
		pio_putstr( "\nCannot open AIC file.\n" );
		return;
		}
	i = pio_fread( fp, 4, (char *)( &num ) );
	if ( i < 4 )
		{
		pio_putstr( "\nAIC file read error.\n" );
		return;
		}
	i = pio_fread( fp, num, (char *)buf );
	if ( i < num )
		{
		pio_putstr( "\nAIC file read error.\n" );
		return;
		}
	//	PE texture select registerに値dをセットします.
	FarlSetPETextureReg(bank);
	for ( i = 0; i < ( num / 2 ); i++ )
		{
		// FIFOにデータを16bitデータとして書き込む
		FarlWriteFifoH( buf[i] );
		}
	pio_putstr( "done.\n" );
	return;
	}

/*
 * write texure buffer
 */
void
writetex(int bank, int x, int y, int data)
	{
	FarlSetMemReg(FARL_CMT_BANK_SELECT_REG, bank);
	FarlWriteTxtXYUnpk(x, y, data);
	}

/*
 * パターン情報セット
 */
void
srcset(unsigned short bank, int xsize, int ysize, int xnum, int ynum)
	{
	int	i,j,n;

	for ( i = 0 ; i < ynum ; i++ )
		{
		for ( j = 0 ; j < xnum ; j++ )
			{
			src[charnumber].bank   = bank;
			src[charnumber].x_pos  = j*xsize;
			src[charnumber].y_pos  = i*ysize;
			src[charnumber].x_size = xsize;
			src[charnumber].y_size = ysize;
			src[charnumber].x_hot  = xsize/2;
			src[charnumber].y_hot  = ysize/2;
			charnumber++;
			}
		}
	}

/*
 * システム初期化
 */
void
InitSystem()
	{
	irq_disable();
	cache_clear();
	cache_enable();
    set_irq_mask(
		BIT_IRQM_SIO | 
		BIT_IRQM_7A | 
		BIT_IRQM_7B |
		BIT_IRQM_KING |
		BIT_IRQM_KP |
		BIT_IRQM_EXT |
		BIT_IRQM_TMI |
		BIT_IRQM_AERR |
		0
		);

	set_irq_prio(IRQ_PRIOA, IRQ_KP);
	set_irq_vector(&int_pad, IRQ_LEVELA);

    reset_irq_mask(
//			BIT_IRQM_SIO | 
//			BIT_IRQM_7A | 
//			BIT_IRQM_7B |
//			BIT_IRQM_KING |
			BIT_IRQM_KP |
//			BIT_IRQM_EXT |
//			BIT_IRQM_TMI |
//			BIT_IRQM_AERR |
			0
		);

	set_irq_level(0x0007);
	IrqOn(XINT_72);                /* HuC6272 割り込みを有効に */
	irq_enable();
	init_get_pad();
	get_pad();
	}

/*
 * 画面初期化
 */
void
InitScreen()
	{
	int i;

	init_nt();	// init Hu6261 device
	init_70();
	dispon(bg | spr | bg0 | bg1 | bg2 | bg3 | rain );
	dispoff( /*bg | spr |*/ bg0 | bg1 | bg2 | bg3 | rain );
	set_nt_mode(interlace | inter_sync | mode_5M | mode_sp256 | mode_bg256);

	cel_off(bg);
	cel_off(spr);
	cel_off(bg0);
	cel_off(bg1);
	cel_off(bg2);
	cel_off(bg3);
	cel_off(rain);
	}

/*
 * 文字列表示
 */
void
StrDsp(int x,int y,int z,unsigned char *str)
	{
	int	i,j;
	int	c;
	int	sx,sy;

	StrX = x;
	StrY = y;
	c = 0;
	while(1)
		{
		if ( str[c] == 0x00 ) break;
		if ( str[c] > 0x20 && str[c] <= 0x4f)
			{
			sprput(StrX,StrY,0,z,str[c]-0x20);
			StrX += 12*z/256;
			}
		else if ( str[c] >= 0x50 && str[c] <= 0x7f)
			{
			sprput(StrX,StrY,0,z,str[c]-0x20);
			StrX += 10*z/256;
			}
		else if ( str[c] >= 0xa0 && str[c] <= 0xdf )
			{
			sprput(StrX,StrY,0,z,str[c] - 0xa0 + 96);
			if ( str[c+1] == 0xde || str[c+1] == 0xdf )
				{
				StrX += 4*z/256;
				}
			else
				{
				StrX += 13*z/256;
				}
			}
		else
			{
			StrX += 12*z/256;
			}
		if ( StrX > 255 || str[c] == '\n' )
			{
			StrX = x;
			StrY += 14*z/256;
			}
		c++;
		}
	}

/*
 * スプライト表示
 */
void
sprput(int x,int y,int r,int z,int pat)
	{
	if ( r == 0 && z == 256 )
		{
		// 普通のスプライトのSCTを作成する
		ASLMakeSimpleSprite( &src[pat], x, y, &sct);
		}
	else
		{
		// 拡大・縮小・回転の SCT を生成する(重たい)
		ASLMakeZoomRotateSprite( &src[pat], x, y, r, z, &sct );
		}
	// SCTをテクスチャ・バッファに書き込む
	ASLSetSpriteTable( 15, 0, 1, &sct );
	// SCTを実行する
	ASLExecuteSprite( 15, 0, 1 );
	}

/*
 * 描画後処理
 */
void
dspwait()
	{
	// 描画終了待ち
	ASLSync();
	// ディスプレイバッファのスワップ(フリップ)
	FarlSwapWindow();
	// スワップ(フリップ)待ち
	ASLWaitForSwap();
	}

/*
 * ボタン待ち
 */
void
waitbutton()
	{
	get_pad();
	while(1)
		{
		get_pad();
		if ( (pad00.KD_TRG & KP_1) || (pad00.KD_TRG & KP_run) ) break;
		}
	}

/*
 * プレイヤー移動
 */
void
shipcontrol()
	{
	int	i,a,b;

	if ( ship.flag == 0 )
		{
		deadcount++;
		if ( deadcount > 80 ) gameover();
		return;
		}
	get_pad();
	if ( pad00.KD_DAT & KP_right )
		{
		ship.deg += 8;
		if ( ship.deg > 255 ) ship.deg -= 256;
		}
	else if ( pad00.KD_DAT & KP_left )
		{
		ship.deg -= 8;
		if ( ship.deg < 0 ) ship.deg += 256;
		}
	if ( (pad00.KD_DAT & KP_1) || (pad00.KD_TRG & KP_3) )
		{
		// 加速
		ship.speed++;
		if ( ship.speed > MAXSPEED ) ship.speed = MAXSPEED;
		ship.xspeed = ship.speed * Cos8(ship.deg) / 256;
		ship.yspeed = ship.speed * Sin8(ship.deg) / 256;
		}
	else
		{
		ship.speed--;
		if ( ship.speed < 0 ) ship.speed = 0;
		}
	if ( pad00.KD_TRG & KP_run )
		{
		pauseflag = 1;
		}
	if ( gflag == 0 ) ship.yspeed++;
	ship.x += ship.xspeed;
	ship.y += ship.yspeed;

	if ( ship.y > 200 )
		{
		if ( ship.speed > 2 || ship.yspeed > 2 || ship.xspeed > 2 )
			{
			ship.flag = 0;
			bakuinit();
			strnum = 0;
			return;
			}
		a = ship.x / 16;
		if ( map[a] > 2 )
			{
			ship.flag = 0;
			bakuinit();
			strnum = 3;
			return;
			}
		if ( (ship.deg > 0 && ship.deg < 176)
			|| (ship.deg > 224 && ship.deg < 256) )
			{
			ship.flag = 0;
			bakuinit();
			strnum = 4;
			return;
			}
		// 友達条件
		for ( i = 0 ; i < MAXENEMY ; i++ )
			{
			if ( enemy[i].flag && hitcheck(i) )
				{
				ship.flag = 0;
				enemy[i].flag = 0;
				bakuinit();
				strnum = 2;
				return;
				}
			}
		stageclear();
		}
	if ( ship.x < 0 || ship.x > 255 || ship.y < 0 || ship.y > 255 )
		{
		strnum = 1;
		gameover();
		}
	}

/*
 * ステージクリア
 */
void
stageclear()
	{
	int	i,a;
	unsigned char *dat[4]={
		"NICE!!",
		"ｽｺﾞｰｲ",
		"ﾔｯﾀﾈ",
		"OK!"};

	skipflag = 0;
	a = random(4);
	for ( i = 0 ; i < 180 ; i++ )
		{
		if ( buttoncheck() ) break;
		sprput(64,100,0,256,304+stage);
		StrDsp(110,108,256,dat[a]);
		dspwait();
		}
	enemyinit();
	stage++;
	if ( stage > 7 ) ending();
	gamemain();
	}

/*
 * ゲームオーバー
 */
void
gameover()
	{
	int	i,a;

	a = random(4);
	for ( i = 0 ; i < 180 ; i++ )
		{
		if ( buttoncheck() ) break;
		sprput(64,100,0,256,312+a);
		StrDsp(110,108,256,"GAME OVER");
		StrDsp(48,160,256,strdat[strnum]);
		dspwait();
		}
	title();
	}

/*
 * エンディング
 */
void
ending()
	{
	int	i,a;
	int xx,yy,zz;
	int scrcount;
	int	dat[16]={
		  0, -1, -2,-4,-8,-12,-14,-15,
		-15,-14,-12,-8,-4, -2, -1,  0};
	unsigned char *dat1[16]={
		"Moon Kids' Paradise",
		"Game Design",
		"Program",
		"Graphics",
		"Test Play",
		"Special Thanks",
		"Special Thanks",
		"Special Thanks",
		"Special Thanks",
		"Special Thanks",
		"  - THE END - "};
	unsigned char *dat2[16]={
		"     Staff    ",
		"       ﾋﾂｼﾞｵﾄｺ",
		"       ﾋﾂｼﾞｵﾄｺ",
		"          ﾅﾉﾚｰ",
		"           ﾉﾌﾞ",
		"          Ajax",
		"         ﾀｲﾆｬﾝ",
		"  Bio100% members",
		"   ASCIInet bio.*",
		" NIFTY-Serve FGALGL",
		"     ﾊﾞｲﾊﾞｲ ﾏﾀﾈ!"};

	a = 0;
	scrcount = 180;
	while(1)
		{
		sprput(112,88,0,256,318);
		StrDsp(16,180,256,dat1[a]);
		StrDsp(16,200,256,dat2[a]);
		for ( i = 0 ; i < 8 ; i++ )
			{
			xx = i * 16 + 120;
			yy = 64 + dat[(scrcount+i)%16];
			zz = 160 + i*16;
			sprput(xx,yy,0,256,zz);
			}
		scrcount--;
		if ( scrcount < 0 )
			{
			a++;
			if ( a > 10 ) a = 10;
			scrcount = 180;
			}
		if ( buttoncheck() && a == 11 )
			{
			logodsp();
			title();
			}
		dspwait();
		}
	}

/*
 * 自機初期化
 */
void
shipinit()
	{
	int	i;

	for ( i = 0 ; i < MAXBAKU ; i++ )
		{
		baku[i].flag = 0;
		}
	ship.x = 50;
	ship.y = 16;
	ship.pat = stage*16 + 160;
	ship.flag = 1;
	ship.deg = 0;
	ship.speed = 1;
	ship.xspeed = ship.speed * Cos8(ship.deg) / 256;
	ship.yspeed = ship.speed * Sin8(ship.deg) / 256 + 1;
	timecount = 1000 + stage*500;
	}

/*
 * 敵初期化
 */
void
enemyinit()
	{
	int	i;

	for ( i = 0 ; i < MAXENEMY ; i++ )
		{
		if ( enemy[i].flag == 0 )
			{
			enemy[i].flag = 1;
			enemy[i].x = ship.x;
			enemy[i].y = ship.y;
			enemy[i].pat = ship.pat;
			enemy[i].deg = 0;
			break;
			}
		}
	}

/*
 * 敵コントロール
 */
void
enemycontrol()
	{
	int	i,a;

	for ( i = 0 ; i < MAXENEMY ; i++ )
		{
		if ( enemy[i].flag )
			{
			enemy[i].mcount--;
			if ( enemy[i].mcount < 0 )
				{
				enemy[i].xspeed = random(2) - random(2);
				enemy[i].mcount = random(20);
				}
			enemy[i].x += enemy[i].xspeed;
			if ( enemy[i].x < 0 )
				{
				enemy[i].x = 0; 
				enemy[i].mcount = 0;
				}
			else if ( enemy[i].x > 255 )
				{
				enemy[i].x = 255;
				enemy[i].mcount = 0;
				}
			a = enemy[i].x/16;
			enemy[i].y = 200 - map[a];
			}
		}
	}

/*
 * 敵描画
 */
void
enemydsp()
	{
	int	i,zz;

	for ( i = 0 ; i < MAXENEMY ; i++ )
		{
		if ( enemy[i].flag )
			{
			zz = enemy[i].pat + aflag/8;
			sprput(enemy[i].x,enemy[i].y,0,256,zz);
			}
		}
	}

/*
 * 爆発初期化
 */
void
bakuinit()
	{
	int	i,j;
	int	dat[4]={135,138,140,142};

	for ( i = 0 ; i < MAXBAKU ; i++ )
		{
		baku[i].flag = 1;
		baku[i].x = ship.x;
		baku[i].y = ship.y;
		baku[i].deg = random(256);
		baku[i].xspeed = random(5) - random(5);
		baku[i].yspeed = random(5) - random(5);
		baku[i].pat = dat[random(4)] + 160;
		baku[i].speed = 256;
		}
	}

/*
 * 爆発コントロール
 */
void
bakucontrol()
	{
	int	i;

	for ( i = 0 ; i < MAXBAKU ; i++ )
		{
		if ( baku[i].flag )
			{
			baku[i].x += baku[i].xspeed;
			baku[i].y += baku[i].yspeed;
			baku[i].speed += 10;
			if ( baku[i].x < 0 || baku[i].x > 255
				|| baku[i].y < 0 || baku[i].y > 224
				|| baku[i].speed > 510 ) baku[i].flag = 0;
			}
		}
	}

/*
 * 爆発描画
 */
void
bakudsp()
	{
	int	i,zz;

	for ( i = 0 ; i < MAXBAKU ; i++ )
		{
		if ( baku[i].flag )
			{
			zz = baku[i].pat + aflag%2;
			sprput(baku[i].x,baku[i].y,0,256,zz);
			}
		}
	}

/*
 * 乱数発生
 */
int
random(int num)
	{
	unsigned int a;

	randomseed = randomseed * 1103515245 + 12345;
	a = (randomseed/0x10000) % 0x8000;
	a %= num;
	return a;
	}

/*
 * ☆初期化
 */
void
starinit()
	{
	int	i;

	for ( i = 0 ; i < MAXSTAR ; i++ )
		{
		star[i].x = random(256);
		star[i].y = random(200);
		}
	}

/*
 * ☆表示
 */
void
stardsp()
	{
	int	i,zz;

	for ( i = 0 ; i < MAXSTAR ; i++ )
		{
		zz = 160 + 133 + aflag / 8;
		sprput(star[i].x,star[i].y,0,256,zz);
		}
	}

/*
 * マップ初期化
 */
void
mapinit()
	{
	int	i;

	for ( i = 0 ; i < MAPX ; i++ )
		{
		map[i] = random(3);
		}
	for ( i = 0 ; i < stage ; i++ )
		{
		map[random(MAPX)] = random(2) + 3;
		}
	}

/*
 * マップ表示
 */
void
mapdsp()
	{
	int	i;

	for ( i = 0 ; i < MAPX ; i++ )
		{
		sprput(i*16+8,200,0,256,map[i]+288);
		}
	}

/*
 * 自機関係表示
 */
void
shipdsp()
	{
	int	i,dd,zz;

	if ( ship.flag == 0 ) return;
	// 自キャラ
	dd = 3600 * (ship.deg+64) / 256;
	zz = ship.pat + aflag / 8;
	sprput(ship.x,ship.y,dd,256,zz);
	}

/*
 * ADPCMファイルの読込
 */
int
adpload(int num, unsigned char *filename)
	{
	// ファイルオープン
	if ( (fh = pio_fopen(filename, "rb")) == -1 )
		{
		pio_putstr("ファイルが開けません。\n");
		return	0;
		}
	// ヘッダーの読み込み
	if ( pio_fread(fh,sizeof(ADPFILEHEAD),&aFileHead[num])
		!= sizeof(ADPFILEHEAD) )
		{
		pio_putstr("ファイルフォーマット異常\n");
		pio_fclose(fh);
		return	0;
		}
	if ( aFileHead[num].afFileID != ID_RIFF || aFileHead[num].afFileType
		!= ID_WAVE || aFileHead[num].afFormatID != ID_FMT  )
		{
		pio_putstr("ヘッダーが異常です。\n");
		pio_fclose(fh);
		return 0;
		}
	// データの読み込み
	pio_putstr("ADPCM DATA Loading...\n");
	pio_fseek(fh,0,0);		// ファイルの先頭に移動
	// ヘッダーに書いてあるサイズ + ヘッダー分読み込む
	if ( pio_fread(fh, aFileHead[num].afDataSize + sizeof(ADPFILEHEAD)
		,pcmbuffer) != aFileHead[num].afDataSize + sizeof(ADPFILEHEAD) )
		{
		pio_putstr("ファイルの長さが異常です。\n");
		pio_fclose(fh);
		return	0;
		}
	// データをKRAMに転送し、構造体にパラメータをセットする
	pcmblock += AdpcmDataSet(&pInfo[num], (unsigned short *)pcmbuffer,
									(unsigned short)pcmblock, PCM_NORMAL);
	pio_fclose(fh);
//	AdpcmPlay(CHANNEL_1,&pInfo[num]);
//	AdpcmWait(CHANNEL_1);
	return	1;
	}

/*
 * 当たり判定
 */
int
hitcheck(int num)
	{
	int	a,b;

	if ( ship.x > enemy[num].x )
		{
		a = ship.x - enemy[num].x;
		}
	else
		{
		a = enemy[num].x - ship.x;
		}
	if ( ship.y > enemy[num].y )
		{
		b = ship.y - enemy[num].y;
		}
	else
		{
		b = enemy[num].y - ship.y;
		}
	if ( a < 8 && b < 8 ) return	1;
	return 0;
	}

/*
 * 数値を表示する
 */
void
numdsp(int x,int y,unsigned long val)
	{
	static char dectbl[] = "0123456789";
	static char str[12];
	int i,c;

	str[10] = '\0';
	for ( i = 9 ; i >= 0 ; i--)
		{
		str[i] = dectbl[val % 10];
		val /= 10;
		}
	c = 0;
	for  ( i = 0 ; i < 10 ; i++ )
		{
		sprput(x+i*8,y,0,256,str[c]-0x20);
		c++;
		}
	}

/*
 * パレット変更
 */
void
PaletteChange(int palettenumber, unsigned short yuv)
	{
	unsigned short	dat[2];

	dat[0] = yuv;
	write_pallet_datas(palettenumber, &dat[0], 1);
	}

/*
 * パレット変更2
 */
void
PaletteChangeBW(int mode,int start,int end)
	{
	int	i;
	unsigned short	dat[2]={0x0088,0xff88};

	if ( mode == 0 )
		{
		// 真っ黒
		for ( i = start ; i < end+1 ; i++ )
			{
			write_pallet_datas(i, &dat[0], 1);
			}
		}
	else
		{
		// 真っ白
		for ( i = start ; i < end+1 ; i++ )
			{
			write_pallet_datas(i, &dat[1], 1);
			}
		}
	}

/*
 * パレットフェードイン、フェードアウト
 */
void
PaletteFadeBlack(int mode,int start, int end)
	{
	int	i,j;

	if ( mode )
		{
		// fadein
		for ( i = 0 ; i < FADERATE + 1 ; i++ )
			{
			for ( j = start ; j < end+1 ; j++ )
				{
				MakePaletteDataBlack(i,j);
				}
			if ( buttoncheck() ) return;
			VSyncWait();
			write_pallet_datas(start, workdat, (end-start)+1 );
			}
		}
	else
		{
		// fadein
		for ( i = FADERATE ; i >= 0 ; i-- )
			{
			for ( j = start ; j < end+1 ; j++ )
				{
				MakePaletteDataBlack(i,j);
				}
			if ( buttoncheck() ) return;
			VSyncWait();
			write_pallet_datas(start, workdat, (end-start)+1 );
			}
		}
	}

/*
 * パレットホワイトイン、ホワイトアウト
 */
void
PaletteFadeWhite(int mode,int start, int end)
	{
	int	i,j;

	if ( mode )
		{
		// whitein
		for ( i = 0 ; i < FADERATE + 1 ; i++ )
			{
			for ( j = start ; j < end+1 ; j++ )
				{
				MakePaletteDataWhite(i,j);
				}
			if ( buttoncheck() ) return;
			VSyncWait();
			write_pallet_datas(start, workdat, (end-start)+1 );
			}
		}
	else
		{
		// fadewhiteout
		for ( i = FADERATE ; i >= 0 ; i-- )
			{
			for ( j = start ; j < end+1 ; j++ )
				{
				MakePaletteDataWhite(i,j);
				}
			if ( buttoncheck() ) return;
			VSyncWait();
			write_pallet_datas(start, workdat, (end-start)+1 );
			}
		}
	}

/*
 * 1ボタンチェック
 */
int
buttoncheck()
	{
	get_pad();
	if ( pad00.KD_DAT & KP_1 )
		{
		skipflag = 1;
		return	1;
		}
	return	0;
	}

/*
 * ウェイト
 */
void
Wait(int c)
	{
	int	i,j;
	int	a,b;

	for ( i = 0 ; i < c ; i++ )
		{
		if ( buttoncheck() ) return;
		VSyncWait();
		}
	}

/*
 * ロゴ表示
 */
void
logodsp()
	{
	int	i,j,k,l;

/*	PaletteFadeBlack(0,0,511);
	Wait(60);
	if ( skipflag ) return;
	// NECロゴ
	for ( i = 0 ; i < 16 ; i++ )
		{
		for ( j = 0 ; j < 16 ; j++ )
			{
			sprput(i*16+8,j*16+8,0,256,DAR_WHITE);
			}
		}
	sprput(128,120,0,256,DAR_NEC);
	dspwait();
	PaletteFadeBlack(1,0,511);
	Wait(120);
	if ( skipflag ) return;
*/	PaletteFadeWhite(0,0,511);
	Wait(60);
	if ( skipflag ) return;

	// Bio100%ロゴ
	for ( i = 0 ; i < FADERATE+1 ; i++ )
		{
		for ( j = 0 ; j < 512 ; j++ )
			{
			MakePaletteDataWhite(i,j);
			}
		if ( buttoncheck() ) return;
		VSyncWait();
		write_pallet_datas(0, workdat, 512);
		for ( k = 0 ; k < 16 ; k++ )
			{
			for ( l = 0 ; l < 16 ; l++ )
				{
				sprput(k*16+8,l*16+8,0,256,DAR_WHITE);
				}
			}
		sprput(128,120,(FADERATE-i)*32,256+(FADERATE-i)*32,DAR_BIO);
		dspwait();
		}
	if ( skipflag ) return;
	Wait(120);
	if ( skipflag ) return;
	PaletteFadeBlack(0,0,511);
	Wait(60);
	}

/*
 * パレットデータ作成
 */
void
MakePaletteDataBlack(int i, int j)
	{
	int	a,b,c,p;

	a = (i5c4yuv_col[j] & 0xff00) * i / FADERATE;
	a &= 0xff00;
	p = i5c4yuv_col[j] & 0x00f0;
	if ( p > 0x0080 )
		{
		b = 0x0080 + (p - 0x0080) * i / FADERATE;
		}
	else
		{
		b = 0x0080 - (0x0080 - p) * i / FADERATE;
		}
	b &= 0x00f0;
	c = (0x0008 - (i5c4yuv_col[j] & 0xfff0)) * i / FADERATE;
	p = i5c4yuv_col[j] & 0x000f;
	if ( p > 0x0008 )
		{
		c = 0x0008 + (p - 0x0008) * i / FADERATE;
		}
	else
		{
		c = 0x0008 - (0x0008 - p) * i / FADERATE;
		}
	c &= 0x000f;
	workdat[j] = a | b | c;
	}

/*
 * パレットデータ作成2
 */
void
MakePaletteDataWhite(int i, int j)
	{
	int	a,b,c;
	unsigned short	p;

	p = i5c4yuv_col[j] & 0xff00;
	a = p + ((0xff00 - p) * (FADERATE-i) / FADERATE);
	a &= 0xff00;

	p = i5c4yuv_col[j] & 0x00f0;
	if ( p > 0x0080 )
		{
		b = 0x0080 + (p - 0x0080) * i / FADERATE;
		}
	else
		{
		b = 0x0080 - (0x0080 - p) * i / FADERATE;
		}
	b &= 0x00f0;
	c = (0x0008 - (i5c4yuv_col[j] & 0xfff0)) * i / FADERATE;
	p = i5c4yuv_col[j] & 0x000f;
	if ( p > 0x0008 )
		{
		c = 0x0008 + (p - 0x0008) * i / FADERATE;
		}
	else
		{
		c = 0x0008 - (0x0008 - p) * i / FADERATE;
		}
	c &= 0x000f;
	workdat[j] = a | b | c;
	}

